package com.finalx.TrafficBytes;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.NetworkInfo;
import android.net.TrafficStats;
import android.os.Handler;
import android.os.IBinder;
import android.text.format.Time;
import android.util.Log;
import android.net.ConnectivityManager;

public class TrafficWatcherService extends Service {
	
	private final String TAG = "TrafficBytes:@@Service";
	private final long mRefreshIntvalMillis = 5 * 1000;
	private final int DATABASE_VERSION = 1;
	
	private MyDbHelper mDbHelper = null;
	private SQLiteDatabase mDb = null;
	ConnectivityManager mConnMgr = null;
	NetworkInfo mMobileNetworkInfo = null;
	private boolean mTodayHasRec = false;
	
	private Handler mHandler = new Handler();
	private Time mTime = null;
	private long mResetBytesDelayMillis = 0;
	protected int refreshCounter = 0;
	private long mTxBytes = 0;
	private long mRxBytes = 0;
	private long mTxBytesOld = 0;
	private long mRxBytesOld = 0;
	private long mTxBytesToday = 0;
	private long mRxBytesToday = 0;
	
    private Runnable mTasks = new Runnable(){  
    	public void run(){  
          refreshBytes();
          refreshCounter  ++;
          mHandler.postDelayed(mTasks, mRefreshIntvalMillis);
       }
    };
    
    private long mTimeTickCount = 0;
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
		
		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			if(intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
				//
				//will do refresh inside this in the furture
				//
				Log.d(TAG, "time tick broadcast received :::: " + (++mTimeTickCount));
			}
		}
	};
			
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		mTime = new Time();
		mTime.setToNow();
		mResetBytesDelayMillis = ((23 - mTime.hour)*60*60 + (59 - mTime.minute)*60 + (59 - mTime.second)) * 1000;
		mConnMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		Log.d(TAG, "@@onCreat: " + mResetBytesDelayMillis/1000 + " seconds left to reset bytes count");
		Log.d(TAG, "substracted mTime in String = " + mTime.toString().substring(0, "YYYYMMDD".length()));
		
		//IntentFilter intentFilter = new IntentFilter(Intent.ACTION_TIME_TICK);
		//registerReceiver(mReceiver, intentFilter);
		mDbHelper = new MyDbHelper(this, MyDbHelper.DATABASE_NAME, null, DATABASE_VERSION);
		mDb = mDbHelper.getWritableDatabase();
		
		readTodayTrafficFromDb();
		
		mHandler.post(mTasks);
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		return super.onStartCommand(intent, flags, startId);
	}
	

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	protected void refreshBytes() {
		// TODO Auto-generated method stub
		mResetBytesDelayMillis -= mRefreshIntvalMillis;
		if(mResetBytesDelayMillis <= 0) {
			mTxBytesToday = mRxBytesToday = 0;
			mResetBytesDelayMillis = 24 * 60 * 60 * 1000;
			mTodayHasRec = false;
			Log.d(TAG, "@@Reset Today's Bytes");
			return;
		}
		
		
		//mMobileNetworkInfo = mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
		mMobileNetworkInfo = mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
		if(mMobileNetworkInfo == null || (!mMobileNetworkInfo.isAvailable()) || (!mMobileNetworkInfo.isConnectedOrConnecting())){
			Log.d(TAG, "mobile network is not avalible, exit +++++------");
			return ;
		}

		setTxRxSinceBoot();
		if(mTxBytes == TrafficStats.UNSUPPORTED || mRxBytes == TrafficStats.UNSUPPORTED) {
			Log.d(TAG, "getMobileTx(Rx)Bytes() is not supported, service will stop by self");
			this.onDestroy();
			this.stopSelf();
			return;
		} 
		
		mTxBytesToday += mTxBytes - mTxBytesOld;
		mRxBytesToday += mRxBytes - mRxBytesOld;
		
		Log.d(TAG, "Traffic Bytes Usage +++++++++++");
		Log.d(TAG, "Since Boot up:mobile net work tx/1000 = :" + mTxBytes/1000 + "K, rx/1000 = :" + mRxBytes/1000 + "K");
		Log.d(TAG, "Today's Usage:mobile net work tx/1000 = :" + mTxBytesToday/1000 + "K, rx/1000 = :" + mRxBytesToday/1000 + "K");
		Log.d(TAG, "Traffic Bytes Usage ------------");
		
		mTxBytesOld = mTxBytes;
		mRxBytesOld = mRxBytes;
		
		setTodayTrafficToDb();
		
	}
	
	private void setTxRxSinceBoot() {
		mTxBytes = TrafficStats.getMobileTxBytes();
		mRxBytes = TrafficStats.getMobileRxBytes();
	}
	
	private void readTodayTrafficFromDb() {
		//set mTxBytesToday & mRxBytesToday
		mTime.setToNow();
		
		Cursor mCursor = mDb.query(MyDbHelper.TABLE_NAME, 
				new String[]{MyDbHelper.COLUMN_TYPE, MyDbHelper.COLUMN_TX, MyDbHelper.COLUMN_RX},
				MyDbHelper.COLUMN_DATE + " = ?",
				new String[]{mTime.toString().substring(0, "YYYYMMDD".length())}, 
				null, null, null, null);
		
		int resType = -1;
		mTxBytesToday = mRxBytesToday = 0;
		if(mCursor != null) {
			if (mCursor.getCount() == 0) {
				mCursor.close();
				return;
			}
			mCursor.moveToFirst();
			while(!mCursor.isAfterLast()) {
				resType = mCursor.getInt(mCursor.getColumnIndex(MyDbHelper.COLUMN_TYPE));
				if(resType == MyDbHelper.COLUMN_TYPE_MOBILE) {
					mTodayHasRec = true;
					mTxBytesToday = mCursor.getLong(mCursor.getColumnIndex(MyDbHelper.COLUMN_TX));
					mRxBytesToday = mCursor.getLong(mCursor.getColumnIndex(MyDbHelper.COLUMN_RX));
					Log.d(TAG, "read from db: Today's TX = " + mTxBytesToday + ", Today's RX = " + mTxBytesToday);
					mCursor.close();
					return ;
				}
				mCursor.moveToNext();
			}
		} else {
			Log.e(TAG, "sqlite return NULL while querying");
			return;
		}
	}
	
	private void setTodayTrafficToDb() {
		mTime.setToNow();
		String dateString = mTime.toString().substring(0, "YYYYMMDD".length());
		ContentValues mContentValues = new ContentValues();
		
		mContentValues.put(MyDbHelper.COLUMN_TX, mTxBytesToday);
		mContentValues.put(MyDbHelper.COLUMN_RX, mRxBytesToday);
		
		Log.d(TAG, "@@@mTodayHasRec = " + mTodayHasRec);
		
		if(mTodayHasRec) {
			mDb.update(MyDbHelper.TABLE_NAME, mContentValues, MyDbHelper.COLUMN_DATE + "=?", new String[]{dateString});
		} else {
			mContentValues.put(MyDbHelper.COLUMN_DATE, Integer.parseInt(dateString));
			mContentValues.put(MyDbHelper.COLUMN_TYPE, ConnectivityManager.TYPE_MOBILE);
			mDb.insert(MyDbHelper.TABLE_NAME, null, mContentValues);
			mTodayHasRec = true;
		}
	}


	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		setTodayTrafficToDb();
		//unregisterReceiver(mReceiver);
		mDb.close();
		
		super.onDestroy();
	
	}
	

}
